#!/usr/bin/ruby

require 'gtk2'

class Fixnum
	def repeat(&block)
		times &block
	end
end

class Compiler < Gtk::Window

	def initialize
	  super
	  
	  # Valores padrão
		@time = 0
		@interval = 500
	  @w = 1000
	  @h = 500
	  @ini_x = 0
	  @ini_y = 0
	  @penc = [0, 0, 0]
	  @penw = 1
		@pendw = true
	  @bgc = [40000, 40000, 40000]
	  @ini_angle = 90.0
	  set_title "Trabalho de Compiladores"
	  
	  signal_connect "destroy" do 
	  	Gtk.main_quit 
	  end
	  
	  init_ui
	  set_default_size @w, @h
	  set_window_position Gtk::Window::POS_CENTER
	  show_all
	  
	  @x = @ini_x
	  @y = @ini_y
	  @angle = @ini_angle
	end

	def init_ui
		@darea = Gtk::DrawingArea.new  
		@darea.signal_connect "expose-event" do  
			on_expose
		end
		add @darea
	end

	def on_expose
		run_cmds
	end
	
	def erase_gnu
		@darea.window.clear_area @x-14, @y-12.5, 28, 25
	end

	def draw_gnu
		@gnu = Gtk::Image.new('gnu-small.png').pixbuf
		@darea.window.draw_pixbuf(nil, @gnu, 0, 0, @x-14, @y-12.5, -1, -1, Gdk::RGB::DITHER_NONE, -1, -1)
	end

	# The methods

	def turnleft(angle)
		GLib::Timeout.add(@time) do
			@angle += angle.to_f
			false
		end
		@time += @interval
	end

	def turnright(angle)
		GLib::Timeout.add(@time) do
			@angle -= angle.to_f
			false
		end
		@time += @interval
	end

	def go(x,y)
		GLib::Timeout.add(@time) do
			@x = x
			@y = y
			draw_gnu
			false
		end
		@time += @interval
	end

	def gox(x)
		GLib::Timeout.add(@time) do
			@x = x
			draw_gnu
			false
		end
		@time += @interval
	end	

	def goy(y)
		GLib::Timeout.add(@time) do
			@y = y
			draw_gnu
			false
		end
		@time += @interval
	end
	
	def pencolor(r, g, b)
		GLib::Timeout.add(@time) do
			@darea.style.fg_gc(@darea.state).rgb_fg_color = Gdk::Color.new(r, g, b)
			false
		end
		@time += @interval
	end

	def penwidth(w)
		GLib::Timeout.add(@time) do
			@darea.style.fg_gc(@darea.state).set_line_attributes(w, Gdk::GC::LINE_SOLID, Gdk::GC::CAP_NOT_LAST, Gdk::GC::JOIN_MITER)
			false
		end
		@time += @interval
	end
	
	def canvascolor(r, g, b)
		GLib::Timeout.add(@time) do
			@darea.style.fg_gc(@darea.state).rgb_bg_color = Gdk::Color.new(r, g, b)
			false
		end
		@time += @interval
	end

	def canvassize(w, h)
		GLib::Timeout.add(@time) do
			resize w, h
			false
		end
		@time += @interval
	end

	def forward(distance)
		GLib::Timeout.add(@time) do
			x = @x + distance*Math.cos(@angle*(Math::PI/180.0))
			y = @y - distance*Math.sin(@angle*(Math::PI/180.0))
			@darea.window.draw_line(@darea.style.fg_gc(@darea.state),@x,@y,x,y) if @pendw
			@x = x
			@y = y
			draw_gnu
			false
		end
		@time += @interval
	end

	def backward(distance)
		GLib::Timeout.add(@time) do
			@angle += 180
			x = @x + distance*Math.cos(@angle*(Math::PI/180.0))
			y = @y - distance*Math.sin(@angle*(Math::PI/180.0))
			@darea.window.draw_line(@darea.style.fg_gc(@darea.state),@x,@y,x,y) if @pendw
			@x = x
			@y = y
			draw_gnu
			false
		end
		@time += @interval
	end

	def wait(s)
		@time += s * 1000
	end
	
	def reset
		GLib::Timeout.add(@time) do
		  @darea.window.clear
		  @pendw = true
			@darea.style.fg_gc(@darea.state).set_line_attributes(@penw, Gdk::GC::LINE_SOLID, Gdk::GC::CAP_NOT_LAST, Gdk::GC::JOIN_MITER)
		  @darea.style.fg_gc(@darea.state).rgb_fg_color = Gdk::Color.new(@penc[0], @penc[1], @penc[2])
			@angle = @ini_angle
		  @x = @ini_x
			@y = @ini_y
			draw_gnu
			false
		end
		@time += @interval
	end
	
	def direction(angle)
		GLib::Timeout.add(@time) do
			@angle = -angle
			false
		end
		@time += @interval
	end

	def penup
		GLib::Timeout.add(@time) do
			@pendw = false
			false
		end
		@time += @interval
	end

	def pendown
		GLib::Timeout.add(@time) do
			@pendw = true
			false
		end
		@time += @interval
	end

end
